package com.viknix.threadpool.manager.http.factory;

import com.viknix.threadpool.manager.http.HttpClientBeanHolder;
import com.viknix.threadpool.manager.http.TpmAsyncRestTemplate;
import com.viknix.threadpool.manager.http.TpmRestTemplate;
import com.viknix.threadpool.manager.http.config.HttpClientConfig;
import com.viknix.threadpool.manager.http.util.PropertyUtil;
import com.viknix.threadpool.manager.server.dependence.util.ExceptionUtil;
import com.viknix.threadpool.manager.server.dependence.util.ThreadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @Author: Dongqi
 * @Date: 2021/11/22 10:57
 * @Version 1.0
 * @Description: http client manager.
 */
public final class HttpClientManager {

    private static final Logger LOGGER = LoggerFactory.getLogger(HttpClientManager.class);

    /**
     * Connection timeout and socket timeout with other servers.
     */
    private static final int TIMEOUT = 500;

    private static final TpmRestTemplate TPM_REST_TEMPLATE;

    private static final TpmAsyncRestTemplate TPM_ASYNC_REST_TEMPLATE;

    static {
        // build tpm rest template
        TPM_REST_TEMPLATE = HttpClientBeanHolder.getTpmRestTemplate(new ConfigHttpClientFactory(TIMEOUT, TIMEOUT));
        TPM_ASYNC_REST_TEMPLATE = HttpClientBeanHolder.getTpmAsyncRestTemplate(
                new ConfigHttpClientFactory(PropertyUtil.getNotifyConnectTimeout(),
                        PropertyUtil.getNotifySocketTimeout()));

        ThreadUtils.addShutdownHook(new Runnable() {
            @Override
            public void run() {
                shutdown();
            }
        });
    }

    public static TpmRestTemplate getTpmRestTemplate() {
        return TPM_REST_TEMPLATE;
    }

    public static TpmAsyncRestTemplate getTpmAsyncRestTemplate() {
        return TPM_ASYNC_REST_TEMPLATE;
    }

    private static void shutdown() {
        LOGGER.warn("[ConfigServer-HttpClientManager] Start destroying TpmRestTemplate");
        try {
            final String httpClientFactoryBeanName = ConfigHttpClientFactory.class.getName();
            HttpClientBeanHolder.shutdownTpmSyncRest(httpClientFactoryBeanName);
            HttpClientBeanHolder.shutdownTpmAsyncRest(httpClientFactoryBeanName);
        } catch (Exception ex) {
            LOGGER.error("[ConfigServer-HttpClientManager] An exception occurred when the HTTP client was closed : {}",
                    ExceptionUtil.getStackTrace(ex));
        }
        LOGGER.warn("[ConfigServer-HttpClientManager] Destruction of the end");
    }

    /**
     * http client factory.
     */
    private static class ConfigHttpClientFactory extends AbstractHttpClientFactory {

        private final int conTimeOutMillis;

        private final int readTimeOutMillis;

        public ConfigHttpClientFactory(int conTimeOutMillis, int readTimeOutMillis) {
            this.conTimeOutMillis = conTimeOutMillis;
            this.readTimeOutMillis = readTimeOutMillis;
        }

        @Override
        protected HttpClientConfig buildHttpClientConfig() {
            return HttpClientConfig.builder().setConTimeOutMillis(conTimeOutMillis)
                    .setReadTimeOutMillis(readTimeOutMillis).build();
        }
    }
}
